

#ifndef __ERP_COMM_TMEM_TOOL_H__
#define __ERP_COMM_TMEM_TOOL_H__

#include <stdint.h>
#include <string>
#include <unistd.h>
#include <time.h>
#include <map>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sstream>
#include <assert.h>
#include "c2cplatform/component/configcenter/config_client_set.h"
#include "c2cplatform/library/the3/tmem/trmem_cache_lib.h"
#include "c2cplatform/library/basic/c2c_inet_addr.h"
#include "c2cplatform/library/basic/singleton_t.h"
#include "c2cplatform/library/basic/sync_lock.h"
#include "c2cplatform/library/the3/itil/c2c_attr.h"

using namespace ssdasn; 

class ssdasn::trmem_client_api;

namespace erp {
namespace comm {

enum TmemCacheEnum
{
	TMEMCACHE_SET_NO				= 0,
	TMEMCACHE_ERR_NO_DATA			= -13200,
	TMEMCACHE_ERR_NO_KEY			= -13105,
	TMEMCACHE_DEF_EXPIRE_TIME		= 3*3600*24,
	TMEMCACHE_NOKEY_LEN             = 1024,
	TMEMCACHE_DEF_SLOW_TIME			= 20,
	TMEMCACHE_FAILED_FREEZE_TIME	= 30,
	TMEMCACHE_CONNECT_TIMEOUT		= 2500,
	TMEMCACHE_READ_TIMEOUT			= 1000,
	TMEMCACHE_UPDATEADDR_THREDHOLD	= 300,
	TMEMCACHE_BUFFER_SIZE			= 1024*1024+1024,
};

enum TmemCacheErr
{
	ERR_TMEMCACHE_INVALID_PARAM		= 1,
	ERR_TMEMCACHE_DATA_NOTEXIST		= 2,
	ERR_TMEMCACHE_CACHE_FAILED		= 3,
	ERR_TMEMCACHE_SERIALIZE_FAILED	= 4,
	ERR_TMEMCACHE_KEY_NOTHIT		= 5,
};

enum TmemCacheItilEnum
{
	ITIL_WRITE_SLOW			= 1,
	ITIL_READ_SLOW			= 2,
	ITIL_BATCHREAD_SLOW		= 3,
	ITIL_WRITE_ERR			= 4,
	ITIL_READ_ERR			= 5,
	ITIL_BATCHREAD_ERR		= 6,
	ITIL_WRITE_REQ			= 7,
	ITIL_READ_REQ			= 8,
	ITIL_BATCHREAD_REQ		= 9,
	ITIL_BATCHREAD_CELL_REQ	=10,
	ITIL_READ_HIT			=11,
	ITIL_BATCHREAD_CELL_HIT	=12,
	ITIL_NOKEY_REQ          =13,
	ITIL_NOKEY_WRITE        =14,
	ITIL_NOKEY_SLOW         =15,
	ITIL_NOKEY_ERR          =16,
};

enum TmemCacheParamEnum
{
	ITIL_READ		= 1,
	ITIL_BATCHREAD	= 2,
	ITIL_WRITE		= 3,
	ITIL_NO_KEY     = 4,
};

class TmemCacheItil {
public:
    inline TmemCacheItil(const std::map<TmemCacheItilEnum,uint32_t>& mapItil,
			uint16_t wTmemReadSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint16_t wTmemBatchReadSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint16_t wTmemWriteSlowTime=TMEMCACHE_DEF_SLOW_TIME)
	:m_ddwStartTime(0),
	 m_wTmemReadSlowTime(wTmemReadSlowTime),
	 m_wTmemBatchReadSlowTime(wTmemBatchReadSlowTime),
	 m_wTmemWriteSlowTime(wTmemWriteSlowTime),
	 m_wSlowTime(0)
	{
		m_vecItil.resize(ITIL_NOKEY_ERR+1,0);
		for(std::map<TmemCacheItilEnum,uint32_t>::const_iterator it=mapItil.begin();it!=mapItil.end();it++)
		{
			if(it->first>=ITIL_WRITE_SLOW&&it->first<=ITIL_NOKEY_ERR)
			{
				m_vecItil[it->first]=it->second;
			}
		}
	}

	inline TmemCacheItil()
	:m_ddwStartTime(0),
	 m_wTmemReadSlowTime(TMEMCACHE_DEF_SLOW_TIME),
	 m_wTmemBatchReadSlowTime(TMEMCACHE_DEF_SLOW_TIME),
	 m_wTmemWriteSlowTime(TMEMCACHE_DEF_SLOW_TIME),
	 m_wSlowTime(0)
	{
		m_vecItil.resize(ITIL_NOKEY_ERR+1,0);
	}

	inline void Reset(const std::map<TmemCacheItilEnum,uint32_t>& mapItil,
			uint16_t wTmemReadSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint16_t wTmemBatchReadSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint16_t wTmemWriteSlowTime=TMEMCACHE_DEF_SLOW_TIME)
	{
		m_ddwStartTime=0,
		m_wTmemReadSlowTime=wTmemReadSlowTime;
		m_wTmemBatchReadSlowTime=wTmemBatchReadSlowTime,
		m_wTmemWriteSlowTime=wTmemWriteSlowTime,
		m_wSlowTime=0;
		m_vecItil.resize(ITIL_NOKEY_ERR+1,0);
		for(std::map<TmemCacheItilEnum,uint32_t>::const_iterator it=mapItil.begin();it!=mapItil.end();it++)
		{
			if(it->first>=ITIL_WRITE_SLOW&&it->first<=ITIL_NOKEY_ERR)
			{
				m_vecItil[it->first]=it->second;
			}
		}
	}

	inline uint64_t Begin(TmemCacheParamEnum eItilType,uint32_t dwCellNum=1)
	{
		m_ddwStartTime=_GetCurrTime();
		switch(eItilType)
		{
		case ITIL_READ:
			AddItil(ITIL_READ_REQ);
			m_wSlowTime=m_wTmemReadSlowTime;
			m_eSlowItil=ITIL_READ_SLOW;
			m_eErrItil=ITIL_READ_ERR;
			m_eHitItil=ITIL_READ_HIT;
			break;
		case ITIL_BATCHREAD:
			AddItil(ITIL_BATCHREAD_REQ);
			AddItil(ITIL_BATCHREAD_CELL_REQ,dwCellNum);
			m_wSlowTime=m_wTmemBatchReadSlowTime;
			m_eSlowItil=ITIL_BATCHREAD_SLOW;
			m_eErrItil=ITIL_BATCHREAD_ERR;
			m_eHitItil=(TmemCacheItilEnum)0;
			break;
		case ITIL_WRITE:
			AddItil(ITIL_WRITE_REQ);
			m_wSlowTime=m_wTmemWriteSlowTime;
			m_eSlowItil=ITIL_WRITE_SLOW;
			m_eErrItil=ITIL_WRITE_ERR;
			m_eHitItil=(TmemCacheItilEnum)0;
			break;
		case ITIL_NO_KEY:
		    AddItil(ITIL_NOKEY_REQ);
			m_wSlowTime=m_wTmemWriteSlowTime;
			m_eSlowItil=ITIL_NOKEY_SLOW;
			m_eErrItil=ITIL_NOKEY_ERR;
			m_eHitItil=(TmemCacheItilEnum)0;
			break;
		}
		
		return m_ddwStartTime;
	}

	inline uint64_t End(int32_t dwRetCode,uint32_t dwHitCellNum=0)
	{
		uint64_t ddwNow=0;
		if(m_wSlowTime!=0)
		{
			ddwNow=_GetCurrTime();
			if(m_ddwStartTime+m_wSlowTime<ddwNow)
			{
				AddItil(m_eSlowItil);
			}
		}
		if(dwRetCode!=0&&dwRetCode!=ERR_TMEMCACHE_DATA_NOTEXIST&&dwRetCode!=ERR_TMEMCACHE_KEY_NOTHIT)
		{
			AddItil(m_eErrItil);
		}
		else if(dwRetCode!=ERR_TMEMCACHE_KEY_NOTHIT)
		{
			AddItil(m_eHitItil);
		}
		if(dwHitCellNum!=0)
		{
			AddItil(ITIL_BATCHREAD_CELL_HIT);
		}
		return ddwNow;
	}

	inline void AddItil(TmemCacheItilEnum eItil,uint32_t dwNum=1)
	{
		Attr_API2(m_vecItil[eItil],dwNum);
	}
private:
	inline uint64_t _GetCurrTime() {
		struct timeval stTime;
		gettimeofday(&stTime, NULL);
		uint64_t ddwTime = stTime.tv_sec * 1000ull;
		return ddwTime + stTime.tv_usec / 1000;
	}

private:
	uint64_t m_ddwStartTime;
	uint16_t m_wTmemReadSlowTime;
	uint16_t m_wTmemBatchReadSlowTime;
	uint16_t m_wTmemWriteSlowTime;
	uint16_t m_wSlowTime;
	TmemCacheItilEnum m_eSlowItil;
	TmemCacheItilEnum m_eErrItil;
	TmemCacheItilEnum m_eHitItil;
	std::vector<uint32_t> m_vecItil;
};

typedef std::map<std::string,uint32_t> CacheFailedKey;

class CTmemClientOp {
public:
    CTmemClientOp();
    ~CTmemClientOp();

public:
	template<class T_DATA>
	uint32_t GetData(const std::string &strKey,T_DATA&oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid=0);

	template<class T_DATA>
	uint32_t AddData(const std::string &strKey,T_DATA&oData,uint32_t dwCacheExpireTime=0,const uint32_t dwBid=0);
	
	uint32_t AddNoKeyData(const std::string&strKey,uint32_t dwCacheExpireTime=0,const uint32_t dwBid=0);

	template<class T_DATA>
	uint32_t GetSimpleData(const std::string &strKey,T_DATA&oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid=0);

	template<class T_DATA>
	uint32_t AddSimpleData(const std::string &strKey,T_DATA&oData,uint32_t dwCacheExpireTime=0,const uint32_t dwBid=0);

	template<class T_DATA>
	uint32_t GetMulData(
			const std::vector<std::string> &vecKey,
			std::vector<T_DATA>& vecData,
			CacheFailedKey& oFailKey,
			std::vector<uint32_t>&vecCacheExpireTime,
			const uint32_t dwBid=0);

	template<class T_DATA>
	uint32_t GetMulSimpleData(
			const std::vector<std::string> &vecKey,
			std::vector<T_DATA>& vecData,
			CacheFailedKey& oFailKey,
			std::vector<uint32_t>&vecCacheExpireTime,
			const uint32_t dwBid=0);

    template<class T_DATA>
    uint32_t GetMulSimpleData(
            const std::vector<std::string>& vecKey,
            std::map<std::string, T_DATA>& mapKeyData,
            CacheFailedKey& oFailKey,
            std::map<std::string, uint32_t>&mapKey2CacheExpireTime,
            const uint32_t dwBid = 0);

	uint32_t DelData(const std::string &strKey,const uint32_t dwBid=0);

	int32_t Initialize(
			const std::string& strSvrName,
			uint32_t dwBid,
			const std::map<TmemCacheItilEnum,uint32_t>& mapItil,
			uint64_t dwCacheExpireTime=TMEMCACHE_DEF_EXPIRE_TIME,
			uint16_t wTmemReadSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint16_t wTmemBatchReadSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint16_t wTmemWriteSlowTime=TMEMCACHE_DEF_SLOW_TIME,
			uint32_t dwBufferSize=TMEMCACHE_BUFFER_SIZE,
			uint32_t dwUpdateAddrThreshold=TMEMCACHE_UPDATEADDR_THREDHOLD,
			bool bUserNoKey=true,
			bool bClosedCache=false,
			uint32_t dwReadTimeout=TMEMCACHE_READ_TIMEOUT,
			uint32_t dwFailedFreezeTime=TMEMCACHE_FAILED_FREEZE_TIME,
			uint32_t dwConnectTimeout=TMEMCACHE_CONNECT_TIMEOUT);

	const char* GetLastErrMsg() const
	{
		return m_szErrMsg;
	}

protected:
	uint32_t _CheckIsCacheValid(CByteStreamNetwork &bs,uint32_t &dwCacheExpireTime);

	template<class T_DATA>
	uint32_t _GetCache(const std::string& strKey,T_DATA& oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid);

	template<class T_DATA>
	uint32_t _AddCache(const std::string& strKey,uint32_t dwCacheExpireTime,T_DATA& oData,const uint32_t dwBid);

	template<class T_DATA>
	uint32_t _GetMulCache(
			const std::vector<std::string> &vecKey,
			std::vector<T_DATA>& vecItemDo,
			CacheFailedKey& oFailKey,
			std::vector<uint32_t>&vecCacheExpireTime,
			const uint32_t dwBid);

	template<class T_DATA>
	uint32_t _GetSimpleCache(const std::string& strKey,T_DATA& oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid);

	template<class T_DATA>
	uint32_t _AddSimpleCache(const std::string& strKey,uint32_t dwCacheExpireTime,T_DATA& oData,const uint32_t dwBid);

	template<class T_DATA>
	uint32_t _GetMulSimpleCache(
			const std::vector<std::string> &vecKey,
			std::vector<T_DATA>& vecItemDo,
			CacheFailedKey& oFailKey,
			std::vector<uint32_t>&vecCacheExpireTime,
			const uint32_t dwBid);

	template<class T_DATA>
    uint32_t _GetMulSimpleCache(
            const std::vector<std::string>& vecKey,
            std::map<std::string,T_DATA>& mapKeyData,
            CacheFailedKey& oFailKey,
            std::map<std::string, uint32_t>& mapKey2CacheExpireTime,
            const uint32_t dwBid);

	uint32_t _DelCache(const std::string& strKey,const uint32_t dwBid);
	
	uint32_t _AddNoKeyCache(const std::string&strKey,uint32_t dwCacheExpireTime,const uint32_t dwBid);

	int32_t _UpdateTmemAddr(bool iFirst=false);
private:
	char* m_pBuffer;
	uint32_t m_dwBufferSize;
	uint32_t m_dwAccessCount;
	uint32_t m_dwUpdateAddrThreshold;
	uint32_t m_dwBid;
	bool m_bCacheClose;
	bool m_bUserNoKey;
	uint32_t m_dwReadTimeout;
	uint32_t m_dwFailedFreezeTime;
	uint64_t m_dwCacheExpireTime;
	char m_szErrMsg[512];
	std::string m_strSvrName;
	TmemCacheItil m_oItil;
	std::vector<TServerAddr> m_vecTSvrAddr;
	ssdasn::trmem_client_api m_oTmemApi;
};

inline CTmemClientOp::CTmemClientOp()
:m_pBuffer(NULL),
 m_dwBufferSize(TMEMCACHE_BUFFER_SIZE),
 m_dwAccessCount(0),
 m_dwUpdateAddrThreshold(TMEMCACHE_UPDATEADDR_THREDHOLD),
 m_dwBid(0),
 m_bCacheClose(false),
 m_bUserNoKey(true),
 m_dwReadTimeout(TMEMCACHE_READ_TIMEOUT),
 m_dwFailedFreezeTime(TMEMCACHE_FAILED_FREEZE_TIME),
 m_dwCacheExpireTime(TMEMCACHE_DEF_EXPIRE_TIME)
{}

inline CTmemClientOp::~CTmemClientOp()
{
	if(m_pBuffer!=NULL)
	{
		delete[] m_pBuffer;
		m_pBuffer=NULL;
	}
}

inline int32_t CTmemClientOp::Initialize(
		const std::string& strSvrName,
		uint32_t dwBid,
		const std::map<TmemCacheItilEnum,uint32_t>& mapItil,
		uint64_t dwCacheExpireTime,
		uint16_t wTmemReadSlowTime,
		uint16_t wTmemBatchReadSlowTime,
		uint16_t wTmemWriteSlowTime,
		uint32_t dwBufferSize,
		uint32_t dwUpdateAddrThreshold,
		bool bUserNoKey,
		bool bClosedCache,
		uint32_t dwReadTimeout,
		uint32_t dwFailedFreezeTime,
		uint32_t dwConnectTimeout)
{
	int32_t dwRetCode=0;

	if(dwBid==0)
	{
        snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Error. Bid is 0");
#ifdef CACHE_TOOL
        std::cout<<m_szErrMsg<<std::endl;
#endif
		return -1;
	}

	if(strSvrName.empty())
	{
        snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Error. SvrName is Empty");
#ifdef CACHE_TOOL
        std::cout<<m_szErrMsg<<std::endl;
#endif
		return -1;
	}

	dwRetCode=CONFIG_SET->Initialize();
	if(dwRetCode!=0)
	{
        snprintf(m_szErrMsg,sizeof(m_szErrMsg),"CONFIG_SET->Initialize Failed. ErrCode:%d ErrMsg:%s",dwRetCode,CONFIG_SET->getLastErrMsg());
#ifdef CACHE_TOOL
        std::cout<<m_szErrMsg<<std::endl;
#endif
		return dwRetCode;
	}

	m_strSvrName=strSvrName;
	m_dwBid=dwBid;
	m_dwCacheExpireTime=dwCacheExpireTime;
	m_dwFailedFreezeTime=dwFailedFreezeTime;
	m_dwUpdateAddrThreshold=dwUpdateAddrThreshold;
	m_bUserNoKey=bUserNoKey;
	m_bCacheClose=bClosedCache;
	m_dwReadTimeout=dwReadTimeout;
	m_pBuffer=new char[dwBufferSize];
	assert(m_pBuffer);
	dwRetCode=_UpdateTmemAddr(true);
	if(dwRetCode!=0)
	{
        snprintf(m_szErrMsg,sizeof(m_szErrMsg),"_UpdateTmemAddr Failed. ErrCode:%d ErrMsg:%s",dwRetCode,m_oTmemApi.GetLastErr());
#ifdef CACHE_TOOL
        std::cout<<m_szErrMsg<<std::endl;
#endif
	}

	dwRetCode=m_oTmemApi.config_connect_timeout(dwConnectTimeout);
	if(dwRetCode!=0)
	{
        snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Tmem config_connect_timeout Failed. ErrCode:%d ErrMsg:%s",dwRetCode,m_oTmemApi.GetLastErr());
#ifdef CACHE_TOOL
        std::cout<<m_szErrMsg<<std::endl;
#endif
		return dwRetCode;
	}

	m_oItil.Reset(mapItil,wTmemReadSlowTime,wTmemBatchReadSlowTime,wTmemWriteSlowTime);

	return 0;
}

inline uint32_t CTmemClientOp::_CheckIsCacheValid(CByteStreamNetwork &bs,uint32_t &dwCacheExpireTime)
{
    if(m_bCacheClose)
    {
        return ERR_TMEMCACHE_KEY_NOTHIT;
    }
    
	bool isExist=true;
	uint32_t dwCacheTime =0;
	bs.isStoring(false);

	bs&dwCacheTime;
	bs&isExist;

    dwCacheExpireTime = dwCacheTime;

	if(!isExist)
	{
		return m_bUserNoKey?ERR_TMEMCACHE_DATA_NOTEXIST:ERR_TMEMCACHE_KEY_NOTHIT;
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_GetCache(const std::string& strKey,T_DATA& oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		return iResult;
	}

	if (strKey.empty())
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::string strData;
    int cas = -1;
	iResult=m_oTmemApi.get_v2(dwBid,const_cast<std::string&>(strKey),strData,cas);
	if (0!=iResult)
	{
	    if(TMEMCACHE_ERR_NO_DATA != (int)iResult && TMEMCACHE_ERR_NO_KEY != (int)iResult)
	    {
	    snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Get Failed.Bid:%d,Key:%s,Cas:%d,ErrMsg:%s",
	    		dwBid,strKey.c_str(),cas,m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
        }
	    
		if (TMEMCACHE_ERR_NO_DATA!=iResult&&TMEMCACHE_ERR_NO_KEY!=iResult)
		{
			iResult=ERR_TMEMCACHE_CACHE_FAILED;
		}
		else
		{
			iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		}
        
		return iResult;
	}

	CByteStreamNetwork bs(const_cast<char*>(strData.c_str()),strData.length());
	bs.isStoring(false);

	iResult=_CheckIsCacheValid(bs,dwCacheExpireTime);
	if(iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"_CheckIsCacheValid Failed.Key:%s,RetCode:%d",
          strKey.c_str(),iResult);
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG("%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	if (!oData.Serialize(bs))
	{
		iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	return 0;
}

inline uint32_t CTmemClientOp::_AddNoKeyCache(const std::string&strKey,uint32_t dwCacheExpireTime,const uint32_t dwBid)
{
    int32_t iResult=0;

	if(m_bCacheClose)
	{
		return iResult;
	}

	if (strKey.empty())
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::string& strTmp = const_cast<std::string&>(strKey);

	CByteStreamNetwork bs(m_pBuffer,m_dwBufferSize);

    bool  bTmp = false;
    bs.isStoring(true);
    bs & dwCacheExpireTime;
    bs & bTmp;

    std::string strData;
    strData.assign(m_pBuffer,bs.getWrittenLength());
    int cas = -1;
	iResult=m_oTmemApi.set_v2(dwBid,strTmp,strData,cas,m_dwCacheExpireTime);
	if (0!=iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Set Failed,Bid:%d,Key:%s,Cas:%d,ExpireTime:%ld,ErrMsg:%s",
			dwBid,strKey.c_str(),cas,m_dwCacheExpireTime,m_oTmemApi.GetLastErr());
        
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		iResult=ERR_TMEMCACHE_CACHE_FAILED;
		return iResult;
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_AddCache(const std::string& strKey,uint32_t dwCacheExpireTime,T_DATA& oData,const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		return iResult;
	}

	if (strKey.empty())
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::string& strTmp = const_cast<std::string&>(strKey);

	CByteStreamNetwork bs(m_pBuffer,m_dwBufferSize);
	bool isExist=true;
	bs.isStoring(true);
	bs&dwCacheExpireTime;
	bs&isExist;

	if (!oData.Serialize(bs))
	{
		iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::string strData;
	strData.assign(m_pBuffer,bs.getWrittenLength());
    int cas = -1;
	iResult=m_oTmemApi.set_v2(dwBid,strTmp,strData,cas,m_dwCacheExpireTime);
	if (0!=iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Set Failed,Bid:%d,Key:%s,Cas:%d,ExpireTime:%ld,ErrMsg:%s",
				dwBid,strKey.c_str(),cas,m_dwCacheExpireTime,m_oTmemApi.GetLastErr());
        
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		iResult=ERR_TMEMCACHE_CACHE_FAILED;
		return iResult;
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_GetMulCache(
		const std::vector<std::string>& vecKey,
		std::vector<T_DATA>& vecData,
		CacheFailedKey& oFailKey,
		std::vector<uint32_t>&vecCacheExpireTime,
		const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		return iResult;
	}

	if (vecKey.size()==0)
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. KeySize:%zd",vecKey.size());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::vector<TKeyNodeV2> vecNode;
	vecNode.resize(vecKey.size());
	std::vector<TKeyNodeV2>::iterator itNode=vecNode.begin();

	for(std::vector<std::string>::const_iterator itKey=vecKey.begin();itKey!=vecKey.end();itKey++,itNode++)
	{
		if((*itKey).empty())
		{
			iResult=ERR_TMEMCACHE_INVALID_PARAM;
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",(*itKey).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			return iResult;
		}

		itNode->key=*itKey;
	}

	iResult=m_oTmemApi.getlist_v2(dwBid,vecNode);
	if(0>iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Getlist Failed.Bid:%d,KeySize:%zd,ErrMsg:%s",dwBid,vecNode.size(),m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		iResult=ERR_TMEMCACHE_CACHE_FAILED;
		return iResult;
	}
	
	vecData.reserve(vecKey.size());
	vecCacheExpireTime.reserve(vecKey.size());
	
    uint32_t dwCacheExpireTime = 0;
	for(itNode=vecNode.begin();itNode!=vecNode.end();itNode++)
	{
		if(itNode->retcode!=0)
		{
			oFailKey[itNode->key]=itNode->retcode;
			continue;
		}
		if((itNode->data).empty())
		{
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Data Empty Error. Key:%s",(itNode->key).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(-1,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=ERR_TMEMCACHE_DATA_NOTEXIST;
			continue;
		}

		CByteStreamNetwork bs(const_cast<char*>((itNode->data).c_str()),(itNode->data).length());
		bs.isStoring(false);

		iResult = _CheckIsCacheValid(bs,dwCacheExpireTime);
		if(iResult!=0)
		{
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"_CheckIsCacheValid Failed. Key:%s,RetCode:%d",
               (itNode->key).c_str(),iResult);
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG("%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=iResult;
			continue;
		}

		T_DATA oData;
		if (!oData.Serialize(bs))
		{
			iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",(itNode->key).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=iResult;
			continue;
		}
		vecData.push_back(oData);
        vecCacheExpireTime.push_back(dwCacheExpireTime);
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_GetSimpleCache(const std::string& strKey,T_DATA& oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		return iResult;
	}

	if (strKey.empty())
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"Key is Empty. Key:%s",strKey.c_str());
#else
		std::cout<<"Key is Empty. Key:"<<strKey<<std::endl;
#endif
		return iResult;
	}

	std::string strData;
    int cas = -1;
	iResult=m_oTmemApi.get_v2(dwBid,const_cast<std::string&>(strKey),strData,cas);
	if (0!=iResult)
	{
	    if(TMEMCACHE_ERR_NO_DATA != (int) iResult && TMEMCACHE_ERR_NO_KEY != (int) iResult)
	    {
	    snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Get Failed.Bid:%d,Key:%s,Cas:%d,ErrMsg:%s",
	    		dwBid,strKey.c_str(),cas,m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
        }
		
		if (TMEMCACHE_ERR_NO_DATA!=iResult&&TMEMCACHE_ERR_NO_KEY!=iResult)
		{
			iResult=ERR_TMEMCACHE_CACHE_FAILED;
		}
		else
		{
			iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		}
        
		return iResult;
	}

	CByteStreamNetwork bs(const_cast<char*>(strData.c_str()),strData.length());
	bs.isStoring(false);

	iResult=_CheckIsCacheValid(bs,dwCacheExpireTime);
	if(iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"_CheckIsCacheValid Failed.Key:%s,RetCode:%d",
          strKey.c_str(),iResult);
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG("%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	bs&oData;
	if (!bs.isGood())
	{
		iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_AddSimpleCache(const std::string& strKey, uint32_t dwCacheExpireTime,T_DATA& oData,const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		return iResult;
	}

	if (strKey.empty())
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::string& strTmp = const_cast<std::string&>(strKey);

	CByteStreamNetwork bs(m_pBuffer,m_dwBufferSize);
	bool isExist=true;
	bs.isStoring(true);
	bs&dwCacheExpireTime;
	bs&isExist;
	bs&oData;

	if (!bs.isGood())
	{
		iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::string strData;
	strData.assign(m_pBuffer,bs.getWrittenLength());
    int cas = -1;
	iResult=m_oTmemApi.set_v2(dwBid,strTmp,strData,cas,m_dwCacheExpireTime);
	if (0!=iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Set Failed.Bid:%d,Key:%s,Cas:%d,ErrMsg:%s",
				dwBid,strKey.c_str(),cas,m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		iResult=ERR_TMEMCACHE_CACHE_FAILED;
		return iResult;
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_GetMulSimpleCache(
		const std::vector<std::string>& vecKey,
		std::vector<T_DATA>& vecData,
		CacheFailedKey& oFailKey,
		std::vector<uint32_t>&vecCacheExpireTime,
		const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		return iResult;
	}

	if (vecKey.size()==0)
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. KeySize:%zd",vecKey.size());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::vector<TKeyNodeV2> vecNode;
	vecNode.resize(vecKey.size());

	std::vector<TKeyNodeV2>::iterator itNode=vecNode.begin();
	for(std::vector<std::string>::const_iterator itKey=vecKey.begin();itKey!=vecKey.end();itKey++,itNode++)
	{
		if((*itKey).empty())
		{
			iResult=ERR_TMEMCACHE_INVALID_PARAM;
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",(*itKey).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			return iResult;
		}
		itNode->key=*itKey;
	}

	iResult=m_oTmemApi.getlist_v2(dwBid,vecNode);
	if(0>iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Getlist Failed.Bid:%d,KeySize:%zd,ErrMsg:%s",
				dwBid,vecNode.size(),m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		iResult=ERR_TMEMCACHE_CACHE_FAILED;
		return iResult;
	}
    vecData.reserve(vecKey.size());
	vecCacheExpireTime.reserve(vecKey.size());
    uint32_t dwCacheExpireTime = 0;
	for(itNode=vecNode.begin();itNode!=vecNode.end();itNode++)
	{
		if(itNode->retcode!=0)
		{
			oFailKey[itNode->key]=itNode->retcode;
			continue;
		}
        
		if((itNode->data).empty())
		{
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Data Empty Error. Key:%s",(itNode->key).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(-1,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=ERR_TMEMCACHE_DATA_NOTEXIST;
			continue;
		}

		CByteStreamNetwork bs(const_cast<char*>((itNode->data).c_str()),(itNode->data).length());
		bs.isStoring(false);

		iResult=_CheckIsCacheValid(bs,dwCacheExpireTime);
		if(iResult!=0)
		{
		    snprintf(m_szErrMsg,sizeof(m_szErrMsg),"_CheckIsCacheValid Failed.Key:%s,RetCode:%d",
              (itNode->key).c_str(),iResult);
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		    C2C_WW_LOG("%s",m_szErrMsg);
#endif
#else
		    std::cout<<m_szErrMsg<<std::endl;
#endif
		    oFailKey[itNode->key]=iResult;
		    continue;
		}

		T_DATA oData;
		bs&oData;

		if (!bs.isGood())
		{
			iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",(itNode->key).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=iResult;
			continue;
		}
        
		vecData.push_back(oData);
        vecCacheExpireTime.push_back(dwCacheExpireTime);
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::_GetMulSimpleCache(
		const std::vector<std::string>& vecKey,
		std::map<std::string,T_DATA>& mapKeyData,
		CacheFailedKey& oFailKey,
		std::map<std::string, uint32_t>& mapKey2CacheExpireTime,
		const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		return iResult;
	}

	if (vecKey.size()==0)
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. KeySize:%zd",vecKey.size());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	std::vector<TKeyNodeV2> vecNode;
	vecNode.resize(vecKey.size());

	std::vector<TKeyNodeV2>::iterator itNode=vecNode.begin();
	for(std::vector<std::string>::const_iterator itKey=vecKey.begin();itKey!=vecKey.end();itKey++,itNode++)
	{
		if((*itKey).empty())
		{
			iResult=ERR_TMEMCACHE_INVALID_PARAM;
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",(*itKey).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			return iResult;
		}
		itNode->key=*itKey;
	}

	iResult=m_oTmemApi.getlist_v2(dwBid,vecNode);
	if(0>iResult)
	{
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Getlist Failed.Bid:%d,KeySize:%zd,ErrMsg:%s",
				dwBid,vecNode.size(),m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		iResult=ERR_TMEMCACHE_CACHE_FAILED;
		return iResult;
	}

    uint32_t dwCacheExpireTime = 0;
	for(itNode=vecNode.begin();itNode!=vecNode.end();itNode++)
	{
		if(itNode->retcode!=0)
		{
			oFailKey[itNode->key]=itNode->retcode;
			continue;
		}
        
		if((itNode->data).empty())
		{
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Data Empty Error. Key:%s",(itNode->key).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(-1,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=ERR_TMEMCACHE_DATA_NOTEXIST;
			continue;
		}

		CByteStreamNetwork bs(const_cast<char*>((itNode->data).c_str()),(itNode->data).length());
		bs.isStoring(false);

		iResult=_CheckIsCacheValid(bs,dwCacheExpireTime);
		if(iResult!=0)
		{
		    snprintf(m_szErrMsg,sizeof(m_szErrMsg),"_CheckIsCacheValid Failed.Key:%s,RetCode:%d",
              (itNode->key).c_str(),iResult);
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		    C2C_WW_LOG("%s",m_szErrMsg);
#endif
#else
		    std::cout<<m_szErrMsg<<std::endl;
#endif
		    oFailKey[itNode->key]=iResult;
		    continue;
		}

		T_DATA oData;
		bs&oData;

		if (!bs.isGood())
		{
			iResult=ERR_TMEMCACHE_SERIALIZE_FAILED;
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Serialize Failed. Key:%s",(itNode->key).c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			oFailKey[itNode->key]=iResult;
			continue;
		}
        
        mapKeyData[itNode->key] = oData;
        mapKey2CacheExpireTime[itNode->key] = dwCacheExpireTime;
	}

	return 0;
}

inline uint32_t CTmemClientOp::_DelCache(const std::string& strKey,const uint32_t dwBid)
{
	int32_t iResult=0;

	if(m_bCacheClose)
	{
		return iResult;
	}

	if (strKey.empty())
	{
		iResult=ERR_TMEMCACHE_INVALID_PARAM;
		snprintf(m_szErrMsg,sizeof(m_szErrMsg),"Key is Empty. Key:%s",strKey.c_str());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
		return iResult;
	}

	iResult=m_oTmemApi.del_v2(dwBid,const_cast<std::string&>(strKey));
	if(iResult!=0)
	{
	    if(TMEMCACHE_ERR_NO_DATA != (int) iResult && TMEMCACHE_ERR_NO_KEY != (int) iResult)
	    {
	    snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.Del Failed.Bid:%d,Key:%s,ErrMsg:%s",
	    		dwBid,strKey.c_str(),m_oTmemApi.GetLastErr());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
		C2C_WW_LOG_ERR(iResult,"%s",m_szErrMsg);
#endif
#else
		std::cout<<m_szErrMsg<<std::endl;
#endif
        }
		
		if(TMEMCACHE_ERR_NO_DATA!=iResult&&TMEMCACHE_ERR_NO_KEY!=iResult)
		{
			iResult=ERR_TMEMCACHE_CACHE_FAILED;
		}
		else
		{
			iResult=ERR_TMEMCACHE_KEY_NOTHIT;
		}
        
		return iResult;
	}

	return 0;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::GetData(const std::string &strKey, T_DATA& oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid)
{
	uint32_t dwResult=0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_READ);
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult=_GetCache(strKey,oData,dwCacheExpireTime,dwTmpBid);
	m_oItil.End(dwResult);

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::AddData(const std::string &strKey,T_DATA& oData,uint32_t dwCacheExpireTime,const uint32_t dwBid)
{
	uint32_t dwResult=0;
	uint32_t dwTmpBid=m_dwBid;
    
	m_oItil.Begin(ITIL_WRITE);
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult=_AddCache(strKey,dwCacheExpireTime,oData,dwTmpBid);
	m_oItil.End(dwResult);

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

inline uint32_t CTmemClientOp::AddNoKeyData(const std::string&strKey,uint32_t dwCacheExpireTime,const uint32_t dwBid)
{
    uint32_t dwResult=0;
    uint32_t dwTmpBid=m_dwBid;
    
	m_oItil.Begin(ITIL_NO_KEY);
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult = _AddNoKeyCache(strKey,dwCacheExpireTime,dwTmpBid);
	m_oItil.End(dwResult);

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::GetMulData(
		const std::vector<std::string>& vecKey,
		std::vector<T_DATA>& vecData,
		CacheFailedKey& oFailKey,
		std::vector<uint32_t>&vecCacheExpireTime,
		const uint32_t dwBid)
{
	uint32_t dwResult = 0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_BATCHREAD,vecKey.size());
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult = _GetMulCache(vecKey,vecData,oFailKey,vecCacheExpireTime,dwTmpBid);
	m_oItil.End(dwResult,vecData.size());

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::GetSimpleData(const std::string &strKey, T_DATA& oData,uint32_t &dwCacheExpireTime,const uint32_t dwBid)
{
	uint32_t dwResult=0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_READ);
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult=_GetSimpleCache(strKey,oData,dwCacheExpireTime,dwTmpBid);
	m_oItil.End(dwResult);

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::AddSimpleData(const std::string &strKey, T_DATA& oData,uint32_t dwCacheExpireTime,const uint32_t dwBid)
{
	uint32_t dwResult=0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_WRITE);
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult=_AddSimpleCache(strKey,dwCacheExpireTime,oData,dwTmpBid);
	m_oItil.End(dwResult);

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::GetMulSimpleData(
		const std::vector<std::string>& vecKey,
		std::vector<T_DATA>& vecData,
		CacheFailedKey& oFailKey,
		std::vector<uint32_t>&vecCacheExpireTime,
		const uint32_t dwBid)
{
	uint32_t dwResult = 0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_BATCHREAD,vecKey.size());
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult = _GetMulSimpleCache(vecKey,vecData,oFailKey,vecCacheExpireTime,dwTmpBid);
	m_oItil.End(dwResult,vecData.size());

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

template<class T_DATA>
inline uint32_t CTmemClientOp::GetMulSimpleData(
		const std::vector<std::string>& vecKey,
		std::map<std::string, T_DATA>& mapKeyData,
		CacheFailedKey& oFailKey,
		std::map<std::string, uint32_t>&mapKey2CacheExpireTime,
		const uint32_t dwBid)
{
	uint32_t dwResult = 0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_BATCHREAD,vecKey.size());
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult = _GetMulSimpleCache(vecKey,mapKeyData,oFailKey,mapKey2CacheExpireTime,dwTmpBid);
	m_oItil.End(dwResult,mapKeyData.size());

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

inline uint32_t CTmemClientOp::DelData(const std::string &strKey,const uint32_t dwBid)
{
	uint32_t dwResult = 0;
	uint32_t dwTmpBid=m_dwBid;

	m_oItil.Begin(ITIL_WRITE);
	if(dwBid!=0)
	{
		dwTmpBid=dwBid;
	}
	dwResult=_DelCache(strKey,dwTmpBid);
	m_oItil.End(dwResult);

	if(dwResult!=0)
	{
		_UpdateTmemAddr();
	}

	return dwResult;
}

inline int32_t CTmemClientOp::_UpdateTmemAddr(bool isFirst)
{
	if(isFirst||m_dwAccessCount>m_dwUpdateAddrThreshold)
	{
		int32_t dwRetCode=0;
		std::vector<CInterAddr> vecAddr;
		vecAddr=CONFIG_SET->getAllAddrBySvcNameAndSet(m_strSvrName.c_str(),TMEMCACHE_SET_NO);
		if (0==vecAddr.size())
		{
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"getAllAddrBySvcNameAndSet Failed. SvrName:%s Size:%zd",m_strSvrName.c_str(),vecAddr.size());
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(-1,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			return -1;
		}

		std::vector<TServerAddr> vecTSvrAddr;
		vecTSvrAddr.resize(vecAddr.size());
		std::vector<CInterAddr>::const_iterator it=vecAddr.begin();
        int i = 0;
		
		for(std::vector<CInterAddr>::const_iterator iterAddr=vecAddr.begin();it!=vecAddr.end();it++,i++)
		{
			TServerAddr oAddr;
			snprintf(oAddr.strIP,sizeof(oAddr.strIP),"%s",it->getHost());
			oAddr.usPort=it->getPort();
			vecTSvrAddr.push_back(oAddr);
			
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"AcessIp[%d]:%s,AcessPort[%d]:%d",i,oAddr.strIP,i,oAddr.usPort);
            std::cout<<m_szErrMsg<<std::endl;
		}
	
		m_vecTSvrAddr=vecTSvrAddr;
		m_dwAccessCount=0;

		dwRetCode=m_oTmemApi.config_server_addr(m_vecTSvrAddr,m_dwReadTimeout,m_dwFailedFreezeTime);
		if(dwRetCode!=0)
		{
			snprintf(m_szErrMsg,sizeof(m_szErrMsg),"TmemApi.config_server_addr Failed. AddrSize:%zd ReadTimeout:%u FailedFreezeTime:%u",vecAddr.size(),m_dwReadTimeout,m_dwFailedFreezeTime);
#ifndef CACHE_TOOL
#ifdef C2C_WWLOG
			C2C_WW_LOG_ERR(-1,"%s",m_szErrMsg);
#endif
#else
			std::cout<<m_szErrMsg<<std::endl;
#endif
			return dwRetCode;
		}
		
		return 0;
	}
	else
	{
		++m_dwAccessCount;
		return 0;
	}
}

typedef CSingletonT<erp::comm::CTmemClientOp,CDummyLock> CTmemCacheOpSingleton;
#define TMEM_CACHE_OP CTmemCacheOpSingleton::Instance()
}
}
#endif

